import { systemTaskInfoQuery } from '@/api/task'
import { message, notification, Typography } from 'antd'
import dayjs from 'dayjs'
import { saveAs } from 'file-saver'
import { NavigateFunction } from 'react-router-dom'
export const getDefaultYear = () => {
  const currentDate = dayjs()
  const currentMonth = currentDate.month() + 1
  if (currentMonth === 1 || currentMonth === 2) {
    return currentDate.subtract(1, 'year').format('YYYY')
  } else {
    return currentDate.format('YYYY')
  }
}
export const getRecentSixMonths = () => {
  const endDate = dayjs().endOf('day')
  const startDate = dayjs().subtract(6, 'month').startOf('day')
  return [startDate, endDate]
}
export const getRecentMonths = (customFormat?: string) => {
  const endDate = dayjs()
    .endOf('day')
    .format(customFormat ? customFormat : 'YYYY-MM-DD HH:mm:ss')
  const startDate = dayjs()
    .subtract(6, 'month')
    .startOf('day')
    .format(customFormat ? customFormat : 'YYYY-MM-DD HH:mm:ss')
  return [startDate, endDate]
}
export const getRecentSeventDays = (customFormat?: string) => {
  const endDate = dayjs()
    .subtract(1, 'day')
    .endOf('day')
    .format(customFormat ? customFormat : 'YYYY-MM-DD HH:mm:ss')
  const startDate = dayjs()
    .subtract(7, 'day')
    .startOf('day')
    .format(customFormat ? customFormat : 'YYYY-MM-DD HH:mm:ss')
  return [startDate, endDate]
}
export const downloadByOwnUrl = (url: string) => {
  const start = url.lastIndexOf('/') + 1
  const fileurl = url.slice(start)
  const dotArr = fileurl?.split('.')
  const name = dotArr[0]?.split('_')?.[0]
  if (start >= 0 && name) {
    const extension = dotArr[dotArr.length - 1]
    const fileurlname = name + '.' + extension
    fetch(url)
      .then((response) => response.blob())
      .then((blob) => saveAs(blob, fileurlname))
      .catch((error) => console.error(error))
  } else {
    const dot = url.split('.').pop()
    const tempName = dayjs().valueOf()
    fetch(url)
      .then((response) => response.blob())
      .then((blob) => saveAs(blob, tempName + '.' + dot))
      .catch((error) => console.error(error))
  }
}
export const getNameByOwnUrl = (url: string) => {
  const start = url.lastIndexOf('/') + 1
  const fileurl = url.slice(start)
  const dotArr = fileurl?.split('.')
  const name = dotArr[0]?.split('_')?.[0]
  if (start >= 0 && name) {
    const extension = dotArr[dotArr.length - 1]
    const fileurlname = name + '.' + extension
    return fileurlname
  } else {
    return url
  }
}

export const downloadByUrl = (url: string, filename?: string) => {
  const start = url.lastIndexOf('/') + 1
  const fileurl = url.slice(start)
  const dotArr = fileurl?.split('.')
  const name = dotArr[0]?.split('_')?.[0]
  if (start >= 0 && name) {
    const extension = dotArr[dotArr.length - 1]
    const fileurlname = name + '.' + extension
    fetch(url)
      .then((response) => response.blob())
      .then((blob) => saveAs(blob, fileurlname))
      .catch((error) => console.error(error))
  } else {
    const dot = url.split('.').pop()
    const tempName = dayjs().valueOf()
    fetch(url)
      .then((response) => response.blob())
      .then((blob) => saveAs(blob, (filename ? filename : tempName) + '.' + dot))
      .catch((error) => console.error(error))
  }
}
export const downloadByUrlBigFile = (url: string, filename?: string) => {
  const link = document.createElement('a')
  link.href = url
  link.download = filename || ''
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}
export const checkIsReply = (uuid: string, MAX = 2, timer = 4000): Promise<string | false> => {
  let current = 0 // 当前次数
  return new Promise((resolve) => {
    const check = async () => {
      current++
      const res = await systemTaskInfoQuery<{ fileId: string }>({ uuid })
      if (res?.data?.list && res?.data?.list?.length > 0 && res?.data?.list?.[0]?.fileId) {
        resolve(res?.data?.list?.[0]?.fileId)
        current = 0
      } else if (current <= MAX) {
        setTimeout(check, timer)
      } else {
        resolve(false)
      }
    }
    check()
  })
}
export const exportNotification = async (uuid: string, navigate: NavigateFunction, path = '/task/center/list') => {
  const hasReplyUrl = await checkIsReply(uuid)
  if (hasReplyUrl) {
    const filename = getNameByOwnUrl(hasReplyUrl)
    downloadByUrlBigFile(hasReplyUrl, filename)
    message.success('导出成功')
  } else {
    const key = `open${Date.now()}`
    notification.warning({
      message: (
        <div style={{ userSelect: 'none' }}>
          <div style={{ fontWeight: 500, fontSize: 20 }}>本次导出数据量较大！</div>
          <div>任务执行中，请稍后前往任务中心查看</div>
        </div>
      ),
      description: (
        <Typography.Link
          onClick={() => {
            navigate(path)
            notification.destroy(key)
          }}
          style={{ userSelect: 'none' }}
        >
          点击跳转任务中心
        </Typography.Link>
      ),
      duration: null,
      key,
    })
  }
}

export const importNotification = async (linkUrl: string) => {
  if (linkUrl) {
    const key = `open${Date.now()}`
    notification.open({
      type: 'warning',
      message: <div style={{ fontWeight: 500, userSelect: 'none' }}>存在导入失败的数据</div>,
      description: (
        <Typography.Paragraph>
          <Typography.Link
            onClick={() => {
              downloadByUrl(linkUrl, '批量导入失败详情')
              notification.destroy(key)
            }}
            style={{ marginRight: 4, userSelect: 'none' }}
          >
            点击下载
          </Typography.Link>
          <Typography.Text>获取失败原因</Typography.Text>
        </Typography.Paragraph>
      ),
      duration: null,
      key,
    })
  } else {
    notification.open({
      type: 'success',
      message: '所有数据导入成功',
      duration: 5,
    })
  }
}

export const importNotificationByFirstErrorMsg = async (linkUrl: string, firstErrorMsg: string) => {
  if (linkUrl) {
    const key = `open${Date.now()}`
    notification.open({
      type: 'warning',
      message: <div style={{ fontWeight: 500, userSelect: 'none' }}>存在导入失败的数据</div>,
      description: (
        <Typography.Paragraph>
          <Typography.Paragraph>第一条失败原因：{firstErrorMsg}</Typography.Paragraph>
          <Typography.Link
            onClick={() => {
              downloadByUrl(linkUrl, '批量导入失败详情')
              notification.destroy(key)
            }}
            style={{ marginRight: 4, userSelect: 'none' }}
          >
            点击下载
          </Typography.Link>
          <Typography.Text>获取完整失败原因</Typography.Text>
        </Typography.Paragraph>
      ),
      duration: null,
      key,
    })
  } else {
    notification.open({
      type: 'success',
      message: '所有数据导入成功',
      duration: 5,
    })
  }
}

export const importNotificationSpec = async (
  uuid: string,
  navigate: NavigateFunction,
  path = '/task/center/list',
  timer?: number,
  noDownload?: boolean,
) => {
  const hasReplyUrl = await checkIsReply(uuid, 2, timer)
  if (hasReplyUrl) {
    message.success('导入成功')
    if (noDownload) return
    const filename = getNameByOwnUrl(hasReplyUrl)
    downloadByUrlBigFile(hasReplyUrl, filename)
  } else {
    const key = `open${Date.now()}`
    notification.warning({
      message: (
        <div style={{ userSelect: 'none' }}>
          <div style={{ fontWeight: 500, fontSize: 20 }}>本次导入数据量较大！</div>
          <div>任务执行中，请稍后前往任务中心查看</div>
        </div>
      ),
      description: (
        <Typography.Link
          onClick={() => {
            navigate(path)
            notification.destroy(key)
          }}
          style={{ userSelect: 'none' }}
        >
          点击跳转任务中心
        </Typography.Link>
      ),
      duration: null,
      key,
    })
  }
}

interface TreeNode {
  id: number | string
  productDataType: string
  children?: any[]
  cupType?: string | number
}
export const findDataTypeAndCollectIds = (tree: any[], predicate: (node: TreeNode) => boolean): (string | number)[] => {
  const resultIds: (string | number)[] = []
  function recursiveSearch(node: TreeNode, path: (string | number)[] = [], found = false) {
    const currentPath = [...path, node.id]
    if (predicate(node)) {
      resultIds.push(...currentPath)
      found = true
    }
    if (!found && node.children) {
      for (const child of node.children) {
        recursiveSearch(child, currentPath, found)
      }
    }
  }
  for (const rootNode of tree) {
    recursiveSearch(rootNode)
  }
  return resultIds
}

export const handleDetailFactory = (
  sourceList: IDesListType,
  targetInfo: any,
  set: React.Dispatch<React.SetStateAction<IDesListType>>,
) => {
  const res = sourceList
    ?.filter((item) => !item?.hidden)
    ?.map((item) => {
      if (typeof item.format === 'function') {
        return {
          ...item,
          content: item.format(targetInfo),
        }
      } else {
        return {
          ...item,
          content: targetInfo[item.key + ''] || '-',
        }
      }
    })
  set(res)
}
export const handleDetailFactoryHasNode = (
  sourceList: IDesListType,
  targetInfo: any,
  set: React.Dispatch<React.SetStateAction<IDesListType>>,
) => {
  const res = sourceList
    ?.filter((item) => !item?.hidden)
    ?.map((item: any) => {
      if (typeof item.content !== 'string' && item.formContent != undefined && item.isShowForm != undefined) {
        return {
          ...item,
        }
      } else if (typeof item.format === 'function') {
        return {
          ...item,
          content: item.format(targetInfo),
        }
      } else {
        return {
          ...item,
          content: targetInfo[item.key + ''] || '-',
        }
      }
    })
  set(res)
}
export function formatNumber(numStr: string | number | null | undefined) {
  if (numStr == null || numStr == undefined) return '-'
  // 使用正则表达式匹配整数部分并添加千分位分隔符
  return numStr.toString().replace(/^(\d+)(\.\d+)?$/, function (match, p1, p2) {
    return p1.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (p2 || '')
  })
}

export function handleTemplateStr(key: string, obj: Record<string, any>) {
  if (obj?.required?.includes(key)) {
    return '必填'
  } else if (obj?.notRequired?.includes(key)) {
    return '非必填'
  } else if (obj?.notShow?.includes(key)) {
    return '不显示'
  } else {
    return '-'
  }
}

export function getDateIsLate(planTime: string | undefined | null, actualTime: string | undefined | null): boolean {
  if (planTime == null && actualTime == null) {
    return false
  }
  const plan = dayjs(planTime)
  const actual = dayjs(actualTime)
  if (planTime != null && actualTime == null) {
    return dayjs().isAfter(plan)
  }
  return actual.isAfter(plan)
}

export function compareObjectsByKey(
  obj1: Record<string, any> | undefined,
  obj2: Record<string, any> | undefined,
  originObj: Record<string, any> | null,
  key: string,
) {
  if (originObj && Object.keys(originObj).length === 0) return true
  if (obj1 && obj2 === undefined) return false
  if (obj1 === undefined || obj2 === undefined) return true
  return obj1[key] === obj2[key]
}

export function debounce(fn: any, delay: number) {
  let timeout: ITimeoutType
  return (...set: any) => {
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(() => {
      fn(...set)
    }, delay)
  }
}
/**
 * 计算表格行合并的跨度数组（支持约束条件）
 * @param data 原始数据数组
 * @param keyName 需要合并的字段名
 * @param constraintKey 可选约束字段名（相同字段值时才会继续合并）
 * @returns 行跨度数组（如 [3,0,0,2,0] 表示第0行跨3行，第3行跨2行）
 */
export const calculateRowSpans = <T extends Record<string, any>>(
  data: T[],
  keyName: string,
  constraintKey?: string,
) => {
  const rowSpans = new Array(data.length).fill(0)
  if (data.length === 0) return rowSpans

  let currentValue: any = null
  let currentConstraint: any = constraintKey ? data[0][constraintKey] : null
  let count = 0
  let startIndex = 0

  data.forEach((item, index) => {
    // 重置条件：主字段变化 或 约束字段存在且变化
    const shouldReset = item[keyName] !== currentValue || (constraintKey && item[constraintKey] !== currentConstraint)

    if (shouldReset) {
      if (count > 0) rowSpans[startIndex] = count // 记录上一段的跨度
      currentValue = item[keyName]
      currentConstraint = constraintKey ? item[constraintKey] : null
      count = 1
      startIndex = index
    } else {
      count++
    }

    // 处理最后一项
    if (index === data.length - 1) {
      rowSpans[startIndex] = count
    }
  })

  return rowSpans
}

/**
 * 将目标数据与详情数据关联，补充 id 字段
 * @param {Array} targetData 目标数据（需要补充 id 的数据）
 * @param {Array} detailData 详情数据（包含 id 的数据）
 * @returns {Array} 补充了 id 的目标数据
 */
export function associateIdToTargetData(targetData: any[], detailData: any[], fabricColorType: number | null) {
  // 创建详情数据的副本用于处理（避免修改原数组）
  const availableDetails = [...(detailData || [])]

  return targetData.map((targetItem) => {
    // 如果目标项已有id，则直接返回不处理
    if (targetItem.id != null) {
      return targetItem
    }

    // 在可用详情数据中查找匹配项
    const detailIndex = availableDetails.findIndex((detailItem) => {
      return (
        detailItem.colorCode === targetItem.colorCode &&
        detailItem.fabricCode === targetItem.fabricCode &&
        detailItem.useSite === targetItem.useSite
      )
    })

    // 找到匹配项的情况
    if (detailIndex !== -1) {
      const matchedDetail = availableDetails[detailIndex]
      // 从可用列表中移除已匹配项（防止重复使用）
      availableDetails.splice(detailIndex, 1)
      // 合并数据（保留目标数据所有属性，补充详情数据的id和面料颜色信息）
      return {
        ...targetItem,
        id: matchedDetail.id,
        fabricColorCode:
          fabricColorType != 2
            ? targetItem?.fabricColorCode || matchedDetail.fabricColorCode || null
            : matchedDetail.fabricColorCode || null,
        fabricColorDetailName:
          fabricColorType != 2
            ? targetItem?.fabricColorDetailName || matchedDetail.fabricColorDetailName || null
            : matchedDetail.fabricColorDetailName || null,
      }
    }
    // 未找到匹配项，返回原数据
    return targetItem
  })
}

/**
 * 将目标数据与详情数据关联，补充 id 字段
 * @param {Array} targetData 目标数据（需要补充 id 的数据）
 * @param {Array} detailData 详情数据（包含 id 的数据）
 * @returns {Array} 补充了 id 的目标数据
 */
export function associateIdToTargetDataByManage(targetData: any[], detailData: any[], fabricColorType: number | null) {
  // 创建详情数据的副本用于处理（避免修改原数组）
  const availableDetails = [...(detailData || [])]

  return targetData.map((targetItem) => {
    // 如果目标项已有id，则直接返回不处理
    if (targetItem.id != null) {
      return targetItem
    }

    // 在可用详情数据中查找匹配项
    const detailIndex = availableDetails.findIndex((detailItem) => {
      return (
        detailItem.colorCode === targetItem.colorCode &&
        detailItem.fabricCode === targetItem.fabricCode &&
        detailItem.useSite === targetItem.useSite
      )
    })

    // 找到匹配项的情况
    if (detailIndex !== -1) {
      const matchedDetail = availableDetails[detailIndex]
      // 从可用列表中移除已匹配项（防止重复使用）
      availableDetails.splice(detailIndex, 1)
      // 合并数据（保留目标数据所有属性，补充详情数据的id和面料颜色信息）
      return {
        ...targetItem,
        id: matchedDetail.id,
        fabricColorCode:
          fabricColorType != 2
            ? targetItem?.fabricColorCode || matchedDetail.fabricColorCode || null
            : matchedDetail.fabricColorCode || null,
        oldfabricColorCode:
          fabricColorType != 2
            ? targetItem?.fabricColorCode || matchedDetail.fabricColorCode || null
            : matchedDetail.fabricColorCode || null,
        fabricColorDetailName:
          fabricColorType != 2
            ? targetItem?.fabricColorDetailName || matchedDetail.fabricColorDetailName || null
            : matchedDetail.fabricColorDetailName || null,
        oldfabricColorDetailName:
          fabricColorType != 2
            ? targetItem?.fabricColorDetailName || matchedDetail.fabricColorDetailName || null
            : matchedDetail.fabricColorDetailName || null,
      }
    }
    // 未找到匹配项，返回原数据
    return targetItem
  })
}
export function flattenData(data: any[]) {
  const result = []
  for (const item of data) {
    const { colorList, ...parentProps } = item
    for (const color of colorList) {
      const { fabricList, ...colorProps } = color
      for (const fabric of fabricList) {
        result.push({
          ...fabric,
          ...colorProps,
          ...parentProps,
        })
      }
    }
  }

  return result
}

export function isImageFile(filename: string) {
  if (!filename) return false
  const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
  const lowerCaseFilename = filename.toLowerCase()
  return imageExtensions.some((ext) => lowerCaseFilename.endsWith(ext))
}
